﻿#ifndef _TES_VECTOR4_H_
#define _TES_VECTOR4_H_

#include <assert.h>
#include <math.h>
#include "TesVector3.h"

class TesVector4
{
public:
	float x, y, z, w;

	TesVector4(float X = 0.0f, float Y = 0.0f, float Z = 0.0f, float W = 1.0f)
	{
		x = X;
		y = Y;
		z = Z;
		w = W;
	}

	TesVector4(TesVector3 v3)
	{
		w = 1.0f;
		x = v3.x;
		y = v3.y;
		z = v3.z;
	}

	TesVector4& operator = (const TesVector4& that)
	{
		x = that.x;
		y = that.y;
		z = that.z;
		w = that.w;
		return *this;
	}

	void Zero()
	{
		x = 0.0f;
		y = 0.0f;
		z = 0.0f;
		w = 0.0f;
	}

	float Length() const
	{
		return sqrtf(x * x + y * y + z * z + w * w);
	}

	float SqrLength() const
	{
		return (x * x + y * y + z * z + w * w);
	}

	TesVector4 Normalize() const
	{
		float len = this->Length();
		assert(len != 0.0f);
		return TesVector4(x / len, y / len, z / len, w / len);
	}

	TesVector4 operator + (const TesVector4& that)
	{
		return TesVector4(x + that.x, y + that.y, z + that.z, w + that.w);
	}

	TesVector4 operator - (const TesVector4& that)
	{
		return TesVector4(x - that.x, y - that.y, z - that.z, w - that.w);
	}

	TesVector4 operator * (float K) const
	{
		return TesVector4(x * K, y * K, z * K, w * K);
	}

	float operator * (const TesVector4& that) const
	{
		return (x * that.x + y * that.y + z * that.z + w * that.w);
	}

	TesVector4 CrossProduct(const TesVector4& that) const
	{
		TesVector4 Res;
		Res.x = y * that.z - z * that.y;
		Res.y = z * that.w - w * that.z;
		Res.z = w * that.x - x * that.w;
		Res.w = x * that.y - y * that.x;
		return Res;
	}

	TesVector4 operator / (float K) const
	{
		assert(K != 0.0f);
		return TesVector4(x / K, y / K, z / K, w / K);
	}

	bool operator == (const TesVector4& that)
	{
		return (this->x == that.x && this->y == that.y && this->z == that.z && this->w == that.w);
	}

	float Distance(const TesVector4& that) const
	{
		float SqrDeltaX = (this->x - that.x) * (this->x - that.x);
		float SqrDeltaY = (this->y - that.y) * (this->y - that.y);
		float SqrDeltaZ = (this->z - that.z) * (this->z - that.z);
		float SprDeltaW = (this->w - that.w) * (this->w - that.w);
		return sqrtf(SqrDeltaX + SqrDeltaY + SqrDeltaZ + SprDeltaW);
	}

	void SetVector(TesVector3 Vec3)
	{
		w = 1.0f;
		x = Vec3.x;
		y = Vec3.y;
		z = Vec3.z;
	}

	void GetVector3(TesVector3& Vec3)
	{
		Vec3.x = x;
		Vec3.y = y;
		Vec3.z = z;
	}

	void SetW(float Num)
	{
		w = Num;
	}

	void GetGlVec(float Vec[4])
	{
		Vec[0] = x;
		Vec[1] = y;
		Vec[2] = z;
		Vec[3] = w;
	}

};

inline TesVector4 operator * (float K, const TesVector4& v)
{
	return TesVector4(v.x * K, v.y * K, v.y * K, v.w * K);
}

#endif